package org.yanex.project.api;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.ArrayList;

public class HTTPMethods {

	private static volatile HTTPMethods instance;

	public static HTTPMethods getInstance() {
		HTTPMethods localInstance = instance;
		if (localInstance == null) {
			synchronized (HTTPMethods.class) {
				localInstance = instance;
				if (localInstance == null) {
					instance = localInstance = new HTTPMethods();
				}
			}
		}
		return localInstance;
	}

	private HTTPMethods() {

	}

	public static class HTTPMethodException extends Exception {
		private static final long serialVersionUID = -7271058709074090755L;

	}
	
	public static class Pair<F, S> implements Serializable {
		private static final long serialVersionUID = -777603462449004447L;
		
		private F f;
		private S s;
		
		public Pair(F first, S second) {
			this.f=first;
			this.s=second;
		}
		
		public F first() {
			return f;
		}
		
		public S second() {
			return s;
		}
	}
	
	public static class ParamList extends ArrayList<Pair<String, String>> {
		private static final long serialVersionUID = 6810089292574464170L;
		
		public ParamList() {
			super();
		}
		
		public ParamList add(String param, String value) {
			Pair<String, String> p = new Pair<String, String>(param, value);
			add(p);
			return this;
		}

	}

	public String get(String url) throws HTTPMethodException {
		return get(url, null);
	}

	public String get(String url, ParamList param) throws HTTPMethodException {
		try {
			String data = "";

			if (param != null) {
				for (Pair<String, String> p : param) {
					if (data.length() == 0) {
						data = "?" + URLEncoder.encode(p.first(), "UTF-8") + "="
								+ URLEncoder.encode(p.second(), "UTF-8");
					} else {
						data = data + "&" + URLEncoder.encode(p.first(), "UTF-8")
								+ "=" + URLEncoder.encode(p.second(), "UTF-8");
					}
				}
			}

			URL _url = new URL(url + data);

			URLConnection conn = _url.openConnection();
			InputStream stream = conn.getInputStream();
			String text = convertStreamToString(stream);

			return text;
		} catch (Exception e) {
			e.printStackTrace();
			throw new HTTPMethodException();
		}
	}

	public String post(String url, ParamList param)
			throws HTTPMethodException {
		try {
			if (param == null)
				throw new HTTPMethodException();

			String data = "";

			for (Pair<String, String> p : param) {
				if (data.length() == 0) {
					data = URLEncoder.encode(p.first(), "UTF-8") + "="
							+ URLEncoder.encode(p.second(), "UTF-8");
				} else {
					data = data + "&" + URLEncoder.encode(p.first(), "UTF-8")
							+ "=" + URLEncoder.encode(p.second(), "UTF-8");
				}
			}

			URL _url = new URL(url);

			URLConnection conn = _url.openConnection();
			conn.setDoOutput(true);
			OutputStreamWriter wr = new OutputStreamWriter(
					conn.getOutputStream());
			wr.write(data);
			wr.flush();
			InputStream stream = conn.getInputStream();
			String text = convertStreamToString(stream);

			return text;
		} catch (Exception e) {
			throw new HTTPMethodException();
		}
	}

	private static String convertStreamToString(InputStream is)
			throws UnsupportedEncodingException {
		BufferedReader reader = new BufferedReader(new InputStreamReader(is,
				"utf-8"));
		StringBuilder sb = new StringBuilder();
		String line = null;
		try {
			while ((line = reader.readLine()) != null) {
				sb.append(line + "\n");
			}
		} catch (IOException e) {
			e.printStackTrace();
			return null;
		} finally {
			try {
				is.close();
			} catch (IOException e) {
				e.printStackTrace();
				return null;
			}
		}
		return sb.toString();
	}

}
